//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999  Microsoft Corporation

Module Name:

secur.cpp

Abstract:


Notes:


--*/
/*
------------------------------------------------------------------------------
    Revision History
    Date                Author          Activity ID         Activity Headline
    2007-04-11         qinxuetao       CEDB200051438        Add +CPINC and +CPIN2
    2007-08-02         qinxuetao       WM600009405          For dragonfly, RIL needs to get locking status without password    
    2007-10-12         Wangxiaogang    WM600019541          Add PIN required UI when dialing
    2008-01-15         Cuiguoqing         WM600029021          Modify for Enable entering phone just after unlock phone.
------------------------------------------------------------------------------
*/

#include "precomp.h"

#ifdef WAVECOM_DRIVER
DWORD g_PhoneLockedStatus = RIL_LOCKEDSTATE_UNKNOWN;
BOOL g_bPINRequired = FALSE;
#endif
//
//
//
HRESULT ParseGetUserIdentity(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
    FUNCTION_TRACE(ParseGetUserIdentity);
    LPSTR szUserID = NULL;
#ifdef RIL_WATSON_REPORT
    char* szUserIDCache = g_RilInfoCache.szIMSI;
#endif // RIL_WATSON_REPORT
    HRESULT hr = S_OK;

    szUserID = (LPSTR)AllocBlob(MAXLENGTH_USERID);
    if (!szUserID) {
        hr = E_OUTOFMEMORY;
        goto Error;
    }
    memset(szUserID, 0x00, MAXLENGTH_USERID);

    // Parse "<prefix><IMSI><postfix>"
    if (!ParseRspPrefix(szRsp, szRsp)                                        ||
        !ParseUnquotedString(szRsp, '\r', szUserID, MAXLENGTH_USERID, szRsp) ||
        !ParseRspPostfix(szRsp, szRsp)) {
        hr = E_FAIL;
        goto Error;
    }

#ifdef RIL_WATSON_REPORT
    // Copy IMSI to RIL Info Cache
    strncpy(szUserIDCache, szUserID, MAXLENGTH_USERID);
#endif // RIL_WATSON_REPORT
    
    pBlob = (void*)szUserID;
    cbBlob = MAXLENGTH_USERID;

Error:
    if (FAILED(hr)) {
        FreeBlob(szUserID);
    }
    return hr;
}


//
//
//
HRESULT RILDrv_GetUserIdentity(DWORD dwParam)
{
    FUNCTION_TRACE(RILDrv_GetUserIdentity);
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

    if (!QueueCmd(pHandle, "AT+CIMI\r", CMDOPT_SUPPRESSLOGGING, APIID_GETUSERIDENTITY, ParseGetUserIdentity, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT ParseGetPhoneLockedState(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
    FUNCTION_TRACE(ParseGetPhoneLockedState);
    UINT i;
    DWORD* pdwState = NULL;
    char szState[MAX_PATH];
#ifdef RIL_WATSON_REPORT
    char* szUserIDCache = g_RilInfoCache.szIMSI;
#endif // RIL_WATSON_REPORT
    HRESULT hr = S_OK;

    pBlob = NULL;
    cbBlob = 0;

    pdwState = (DWORD*)AllocBlob(sizeof(DWORD));
    if (!pdwState) {
        hr = E_OUTOFMEMORY;
        goto Error;
    }
    memset(pdwState, 0x00, sizeof(DWORD));

    // Parse "<prefix>+CPIN: <state><postfix>"
    if (!ParseRspPrefix(szRsp, szRsp)                               ||
        !MatchStringBeginning(szRsp, "+CPIN: ", szRsp)              ||
        !ParseUnquotedString(szRsp, '\r', szState, MAX_PATH, szRsp) ||
        !ParseRspPostfix(szRsp, szRsp)) {
        hr = E_FAIL;
        goto Error;
    }
    for (i = 1; i <= NUM_LOCKEDSTATES; i++) {
        if (!strcmp(szState, g_rgszLockedStates[i])) {
            *pdwState = i;
            break;
        }
    }
    if (i > NUM_LOCKEDSTATES) {
        // We couldn't match the response with anything
        *pdwState = RIL_LOCKEDSTATE_UNKNOWN;
    }
    else
    {
        UpdateSIMState(*pdwState);

#ifdef RIL_WATSON_REPORT
        // Send command to update the IMSI in the info cache
        // if the IMSI cache has not been updated yet and the 
        // SIM state is ready.
        if (('\0' == *szUserIDCache) && (RIL_LOCKEDSTATE_READY == *pdwState) )
        {
            QueueCmdIgnoreRsp(APIID_NONE, "AT+CIMI\r", CMDOPT_SUPPRESSLOGGING | CMDOPT_IGNORERADIOOFF, g_TimeoutCmdInit, ParseGetUserIdentity, NULL, 0, 0, 0);
        }
#endif // RIL_WATSON_REPORT
    }

    pBlob = (void*)pdwState;
    cbBlob = sizeof(DWORD);

Error:
    if (FAILED(hr)) {
        FreeBlob(pdwState);
    }
    return hr;
}


//
//
//
HRESULT RILDrv_GetPhoneLockedState(DWORD dwParam)
{
    FUNCTION_TRACE(RILDrv_GetPhoneLockedState);
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

#ifdef WAVECOM_DRIVER
    // HW-SPECIFIC: WaveCom hardware doesn't provide an OK at the end of an AT+CPIN? response

    if (!QueueCmd(pHandle, "AT+CPIN?\r", CMDOPT_NONE, APIID_GETPHONELOCKEDSTATE, NULL, NULL, hr)) {
#else  // WAVECOM_DRIVER

    if (!QueueCmd(pHandle, "AT+CPIN?\r", CMDOPT_NONE, APIID_GETPHONELOCKEDSTATE, ParseGetPhoneLockedState, NULL, hr)) {
#endif // WAVECOM_DRIVER

        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT RILDrv_UnlockPhone(DWORD dwParam, LPCSTR lpszPassword, LPCSTR lpszNewPassword)
{
    FUNCTION_TRACE(RILDrv_UnlockPhone);
    DEBUGCHK(NULL != lpszPassword);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle || !lpszPassword) {
        hr = E_FAIL;
        goto Error;
    }

#ifdef WAVECOM_DRIVER
    if( RIL_LOCKEDSTATE_SIM_PIN2 == g_PhoneLockedStatus 
        || RIL_LOCKEDSTATE_SIM_PUK2 == g_PhoneLockedStatus )
    {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CPIN2=\"%s\"", lpszPassword);
    }
    else
#endif
    {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CPIN=\"%s\"", lpszPassword);
    }

    szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
    DEBUGCHK(NULL != szWalk);

    if (lpszNewPassword) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), ",\"%s\"", lpszNewPassword);
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }
    (void)strncpyz(szWalk, "\r", SECUR_CMDBUF_LENGTH - (szWalk - szCmd));  // NO_TYPO: 30

#ifdef RIL_RADIO_RESILIENCE
        // save the unlock code in case of radio reset 
        SavePINSecure(lpszNewPassword ? lpszNewPassword : lpszPassword);
#endif // RIL_RADIO_RESILIENCE
    
    if (!QueueCmd(pHandle, szCmd, CMDOPT_UNLOCKING | CMDOPT_SUPPRESSLOGGING | CMDOPT_CPINENTERED, APIID_UNLOCKPHONE, NULL, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
static HRESULT ParseGetLockingStatus(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
    FUNCTION_TRACE(ParseGetLockingStatus);
    UINT nValue;
    DWORD* pdwStatus = NULL;
    HRESULT hr = S_OK;

    pBlob = NULL;
    cbBlob = 0;

    pdwStatus = (DWORD*)AllocBlob(sizeof(DWORD));
    if (!pdwStatus) {
        hr = E_OUTOFMEMORY;
        goto Error;
    }
    memset(pdwStatus, 0x00, sizeof(DWORD));

    // Parse "<prefix>+CLCK: <status><postfix>"
    if (!ParseRspPrefix(szRsp, szRsp)                           ||
        !MatchStringBeginning(szRsp, "+CLCK: ", szRsp)          ||
        !ParseUIntAndVerifyAbove(szRsp, TRUE, 2, nValue, szRsp) ||
        !ParseRspPostfix(szRsp, szRsp)) {
        hr = E_FAIL;
        goto Error;
    }
    *pdwStatus = (nValue ? RIL_LOCKINGSTATUS_ENABLED : RIL_LOCKINGSTATUS_DISABLED);

    pBlob = (void*)pdwStatus;
    cbBlob = sizeof(DWORD);

Error:
    if (FAILED(hr)) {
        FreeBlob(pdwStatus);
    }
    return hr;
}


//
//
//
HRESULT RILDrv_GetLockingStatus(DWORD dwParam, DWORD dwFacility, LPCSTR lpszPassword)
{
    FUNCTION_TRACE(RILDrv_GetLockingStatus);
    DEBUGCHK(dwFacility && NUM_LOCKFACILITIES > dwFacility);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

#ifdef EMP_DRIVER
    // EMP doesn't support RIL_LOCKFACILITY_PH_FSIM
    if (RIL_LOCKFACILITY_PH_FSIM == dwFacility)
    {
        hr = E_NOTIMPL;
        goto Error;
    }
#endif

#ifndef WAVECOM_DRIVER
    if (lpszPassword) {
#else
    if (lpszPassword && (RIL_LOCKFACILITY_SIM != dwFacility)) {
#endif
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",2,\"%s\"\r",
                         g_rgszLockFacilities[dwFacility], lpszPassword);
    } else {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",2\r",
                         g_rgszLockFacilities[dwFacility]);
    }
    if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_GETLOCKINGSTATUS, ParseGetLockingStatus, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT RILDrv_SetLockingStatus(DWORD dwParam, DWORD dwFacility, LPCSTR lpszPassword, DWORD dwStatus)
{
    FUNCTION_TRACE(RILDrv_SetLockingStatus);
    DEBUGCHK(dwFacility && NUM_LOCKFACILITIES > dwFacility);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    UINT nValue = 0;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    DWORD dwCommandOpts = CMDOPT_SUPPRESSLOGGING;

    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

    if (RIL_LOCKINGSTATUS_DISABLED == dwStatus) {
        nValue = 0;
    } else if (RIL_LOCKINGSTATUS_ENABLED == dwStatus) {
        nValue = 1;
    } else {
        DEBUGCHK(FALSE);
    }

#ifdef RIL_RADIO_RESILIENCE
        if ((RIL_LOCKFACILITY_SIM == dwFacility) && (lpszPassword) && (RIL_LOCKINGSTATUS_ENABLED == dwStatus))
        {
            dwCommandOpts |= CMDOPT_CPINENTERED;
            SavePINSecure(lpszPassword);
        }
#endif // RIL_RADIO_RESILIENCE

#ifdef EMP_DRIVER
    // EMP doesn't support RIL_LOCKFACILITY_PH_FSIM
    if (RIL_LOCKFACILITY_PH_FSIM == dwFacility)
    {
        hr = E_NOTIMPL;
        goto Error;
    }
#endif // EMP_DRIVER

    if (lpszPassword) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",%u,\"%s\"\r",
                         g_rgszLockFacilities[dwFacility], nValue, lpszPassword);
    } else {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",%u\r",
                         g_rgszLockFacilities[dwFacility], nValue);
    }
    if (!QueueCmd(pHandle, szCmd, dwCommandOpts, APIID_SETLOCKINGSTATUS, NULL, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT RILDrv_ChangeLockingPassword(DWORD dwParam, DWORD dwFacility, DWORD dwOldPasswordType, LPCSTR lpszOldPassword, LPCSTR lpszNewPassword)
{
    FUNCTION_TRACE(RILDrv_ChangeLockingPassword);
    DEBUGCHK(dwFacility && NUM_LOCKFACILITIES > dwFacility);
    DEBUGCHK(NULL != lpszOldPassword);
    DEBUGCHK(NULL != lpszNewPassword);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle || !lpszOldPassword || !lpszNewPassword) {
        hr = E_FAIL;
        goto Error;
    }

    if (RIL_PASSWORDTYPE_PIN == dwOldPasswordType)
    {        
        DWORD dwCommandOpts = CMDOPT_SUPPRESSLOGGING;
#ifdef RIL_RADIO_RESILIENCE
        if ((RIL_LOCKFACILITY_SIM == dwFacility) && (lpszNewPassword))
        {
            dwCommandOpts |= CMDOPT_CPINENTERED;
            SavePINSecure(lpszNewPassword);
        }
#endif // RIL_RADIO_RESILIENCE

#ifdef EMP_DRIVER
        if ((RIL_LOCKFACILITY_PH_SIM != dwFacility) && (RIL_LOCKFACILITY_SIM != dwFacility) &&
            (RIL_LOCKFACILITY_SIM_PIN2 != dwFacility))
        {
            hr = E_NOTIMPL;
            goto Error;
        }
#endif // EMP_DRIVER

        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CPWD=\"%s\",\"%s\",\"%s\"\r",
                         g_rgszLockFacilities[dwFacility], lpszOldPassword, lpszNewPassword);
        if (!QueueCmd(pHandle, szCmd, dwCommandOpts, APIID_CHANGELOCKINGPASSWORD, NULL, NULL, hr)) {
            hr = E_FAIL;
            goto Error;
        }
    }
    else if (RIL_PASSWORDTYPE_PUK == dwOldPasswordType)
    {
        // The "old" password is the PIN unblocking key that is used to
        // unblock either PIN or PIN2.
        DEBUGCHK(RIL_LOCKFACILITY_SIM == dwFacility ||
                   RIL_LOCKFACILITY_SIM_PIN2 == dwFacility);

#if defined (OEM1_DRIVER)
        // This hardware uses ATD to get the desired functionality
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "ATD**05%s*%s*%s*%s#\r",
                         ((RIL_LOCKFACILITY_SIM_PIN2 == dwFacility) ? "2" : ""), lpszOldPassword, lpszNewPassword, lpszNewPassword);
        if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_CHANGELOCKINGPASSWORD, NULL, NULL, hr)) {
            hr = E_FAIL;
            goto Error;
        }
#else
        // Other hardware uses +CPIN and will fail if no PIN request is pending, per GSM 07.07
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CPIN=\"%s\",\"%s\"\r",
                         lpszOldPassword, lpszNewPassword);
        if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING | CMDOPT_UNLOCKING , APIID_CHANGELOCKINGPASSWORD, NULL, NULL, hr)) {
            hr = E_FAIL;
            goto Error;
        }
#endif
    }
    else
    {
        hr = E_INVALIDARG;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
static HRESULT ParseGetCallBarringStatus(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
    FUNCTION_TRACE(ParseGetCallBarringStatus);
    UINT nValue;
    UINT nDummy;
    DWORD* pdwStatus = NULL;
    HRESULT hr = S_OK;

    pBlob = NULL;
    cbBlob = 0;

    pdwStatus = (DWORD*)AllocBlob(sizeof(DWORD));
    if (!pdwStatus) {
        hr = E_OUTOFMEMORY;
        goto Error;
    }
    memset(pdwStatus, 0x00, sizeof(DWORD));

    // Parse "<prefix>+CLCK: <status>"
    if (!ParseRspPrefix(szRsp, szRsp)                           ||
        !MatchStringBeginning(szRsp, "+CLCK: ", szRsp)          ||
        !ParseUIntAndVerifyAbove(szRsp, TRUE, 2, nValue, szRsp)){
        hr = E_FAIL;
        goto Error;
    }
    // Parse "[,<info_class>]"
    if (MatchStringBeginning(szRsp, ",", szRsp))
        if (!ParseUInt(szRsp, TRUE, nDummy, szRsp)){
            hr = E_FAIL;
            goto Error;
        }
    // Parse "<postfix>"
    if (!ParseRspPostfix(szRsp, szRsp)) {
        hr = E_FAIL;
        goto Error;
    }
    *pdwStatus = (nValue ? RIL_BARRINGSTATUS_ENABLED : RIL_BARRINGSTATUS_DISABLED);

    pBlob = (void*)pdwStatus;
    cbBlob = sizeof(DWORD);

Error:
    if (FAILED(hr)) {
        FreeBlob(pdwStatus);
    }
    return hr;
}


//
//
//
HRESULT RILDrv_GetCallBarringStatus(DWORD dwParam, DWORD dwType, DWORD dwInfoClass, LPCSTR lpszPassword)
{
    FUNCTION_TRACE(RILDrv_GetCallBarringStatus);
    DEBUGCHK(dwType && NUM_BARRINGTYPES > dwType);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    UINT nValue = 0;
    UINT i;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

    for (i = 0 ; i < NUM_INFOCLASSES; i++) {
        if (dwInfoClass & g_rgdwInfoClasses[i]) {
            nValue |= (0x01 << i);
        }
    }

    if (RIL_INFOCLASS_SMS != dwInfoClass && (nValue & 0x8))
    {
        nValue -= 8;
    }

#ifdef EMP_DRIVER
    // EMP doesn't support RIL_BARRTYPE_INCOMINGNOTINSIM
    if (RIL_BARRTYPE_INCOMINGNOTINSIM == dwType)
    {
        hr = E_NOTIMPL;
        goto Error;
    }
#endif // EMP_DRIVER

    (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",2", g_rgszBarringTypes[dwType]);
    szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
    DEBUGCHK(NULL != szWalk);

    if (lpszPassword) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), ",\"%s\"", lpszPassword);
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }
    // Only need to add a comma if we'll be adding the infoclass next
    else if ((RIL_INFOCLASS_NONE != nValue) && ((RIL_INFOCLASS_VOICE | RIL_INFOCLASS_DATA | RIL_INFOCLASS_FAX) != nValue)) {
        (void) strncpyz(szWalk, ",", SECUR_CMDBUF_LENGTH - (szWalk - szCmd));  // NO_TYPO: 30
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }
    
    // unspecified infoclass is treated as default
    if ((RIL_INFOCLASS_NONE != nValue) && ((RIL_INFOCLASS_VOICE | RIL_INFOCLASS_DATA | RIL_INFOCLASS_FAX) != nValue)) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), ",%u", nValue);
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }

    (void) strncpyz(szWalk, "\r", SECUR_CMDBUF_LENGTH - (szWalk - szCmd));  // NO_TYPO: 30

    if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_GETCALLBARRINGSTATUS, ParseGetCallBarringStatus, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT RILDrv_SetCallBarringStatus(DWORD dwParam, DWORD dwType, DWORD dwInfoClass, LPCSTR lpszPassword, DWORD dwStatus)
{
    FUNCTION_TRACE(RILDrv_SetCallBarringStatus);
    DEBUGCHK(dwType && NUM_BARRINGTYPES > dwType);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    UINT nValue1;
    UINT nValue2 = 0;
    UINT i;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle) {
        hr = E_FAIL;
        goto Error;
    }

    if (RIL_BARRINGSTATUS_DISABLED == dwStatus) {
        nValue1 = 0;
    } else if (RIL_BARRINGSTATUS_ENABLED == dwStatus) {
        nValue1 = 1;
    } else {
        DEBUGCHK(FALSE);
    }

    for (i = 0 ; i < NUM_INFOCLASSES; i++) {
        if (dwInfoClass & g_rgdwInfoClasses[i]) {
            nValue2 |= (0x01 << i);
        }
    }

    if (RIL_INFOCLASS_SMS != dwInfoClass && (nValue2 & 0x8))
    {
        nValue2 -= 8;
    }

#ifdef EMP_DRIVER
    // EMP doesn't support RIL_BARRTYPE_INCOMINGNOTINSIM
    if (RIL_BARRTYPE_INCOMINGNOTINSIM == dwType)
    {
        hr = E_NOTIMPL;
        goto Error;
    }
#endif // EMP_DRIVER

    (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CLCK=\"%s\",%u", g_rgszBarringTypes[dwType], nValue1);
    szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
    DEBUGCHK(NULL != szWalk);

    if (lpszPassword) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), ",\"%s\"", lpszPassword);
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }
    // Only need to add a comma if we'll be adding the infoclass next
    else if ((RIL_INFOCLASS_NONE != nValue2) && ((RIL_INFOCLASS_VOICE | RIL_INFOCLASS_DATA | RIL_INFOCLASS_FAX) != nValue2)) {
        (void) strncpyz(szWalk, ",", SECUR_CMDBUF_LENGTH - (szWalk - szCmd));  // NO_TYPO: 30
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }
    
    // unspecified infoclass is treated as default
    if ((RIL_INFOCLASS_NONE != nValue2) && ((RIL_INFOCLASS_VOICE | RIL_INFOCLASS_DATA | RIL_INFOCLASS_FAX) != nValue2)) {
        (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), ",%u", nValue2);
        szWalk = strchr(szWalk, '\0');  // NO_TYPO: 27
        DEBUGCHK(NULL != szWalk);
    }

    (void) strncpyz(szWalk, "\r", SECUR_CMDBUF_LENGTH - (szWalk - szCmd));  // NO_TYPO: 30

    if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_SETCALLBARRINGSTATUS, NULL, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}


//
//
//
HRESULT RILDrv_ChangeCallBarringPassword(DWORD dwParam, DWORD dwType, LPCSTR lpszOldPassword, LPCSTR lpszNewPassword)
{
    FUNCTION_TRACE(RILDrv_ChangeCallBarringPassword);
    DEBUGCHK(dwType && NUM_BARRINGTYPES > dwType);
    DEBUGCHK(NULL != lpszOldPassword);
    DEBUGCHK(NULL != lpszNewPassword);

    char szCmd[SECUR_CMDBUF_LENGTH];
    LPSTR szWalk = szCmd;
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle || !lpszOldPassword || !lpszNewPassword) {
        hr = E_FAIL;
        goto Error;
    }

#ifdef EMP_DRIVER
    // EMP doesn't support RIL_BARRTYPE_INCOMINGNOTINSIM
    if (RIL_BARRTYPE_INCOMINGNOTINSIM == dwType)
    {
        hr = E_NOTIMPL;
        goto Error;
    }
#endif // EMP_DRIVER

    (void)_snprintfz(szWalk, SECUR_CMDBUF_LENGTH - (szWalk - szCmd), "AT+CPWD=\"%s\",\"%s\",\"%s\"\r",
                     g_rgszBarringTypes[dwType], lpszOldPassword, lpszNewPassword);
    if (!QueueCmd(pHandle, szCmd, CMDOPT_SUPPRESSLOGGING, APIID_CHANGECALLBARRINGPASSWORD, NULL, NULL, hr)) {
        hr = E_FAIL;
        goto Error;
    }

Error:
    return hr;
}
void RILSecSetPinRequiredFlag(bool flag)
{
    RETAILMSG (1, (TEXT("RILDrv : i : RILSecSetPinRequiredFlag[%d]\r\n"),flag));
    g_bPINRequired = flag;
}

BOOL RILSecGetPinRequiredFlag(void)
{
    RETAILMSG(1, (TEXT("RILDrv : i : RILSecGetPinRequiredFlag[%d]\r\n"),g_bPINRequired));
    return g_bPINRequired;
}
